package com.bjtu.literatureclient.service.sync.impl;

import com.bjtu.literatureclient.api.Constans;
import com.bjtu.literatureclient.api.vo.request.SyncEntityRequest;
import com.bjtu.literatureclient.api.vo.request.SyncJournalPaperRequest;
import com.bjtu.literatureclient.api.vo.request.SyncJournalRequest;
import com.bjtu.literatureclient.api.vo.response.UserSyncRecord;
import com.bjtu.literatureclient.base.exceptions.BaseException;
import com.bjtu.literatureclient.base.exceptions.ExceptionEnum;
import com.bjtu.literatureclient.base.result.Result;
import com.bjtu.literatureclient.base.result.SuccessEnum;
import com.bjtu.literatureclient.dao.authorindex.AuthorIndexDao;
import com.bjtu.literatureclient.dao.journal.IJournalDao;
import com.bjtu.literatureclient.dao.user.UserIndexDao;
import com.bjtu.literatureclient.dao.user.UserUpdateOfVersionAndTableDao;
import com.bjtu.literatureclient.domain.UserUpdateOfVersionAndTable;
import com.bjtu.literatureclient.domain.authorindex.AuthorIndex;
import com.bjtu.literatureclient.domain.journal.JournalChinese;
import com.bjtu.literatureclient.domain.journal.JournalEnglish;
import com.bjtu.literatureclient.domain.journal.JournalPaperChinese;
import com.bjtu.literatureclient.domain.journal.JournalPaperEnglish;
import com.bjtu.literatureclient.domain.user.User;
import com.bjtu.literatureclient.domain.user.UserIndexNoTable;
import com.bjtu.literatureclient.feign.IndexNoFeignService;
import com.bjtu.literatureclient.feign.JournalFeignService;
import com.bjtu.literatureclient.feign.JournalPaperFeignService;
import com.bjtu.literatureclient.service.sync.SynchronizationService;
import com.bjtu.literatureclient.util.UserUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author caiyuli
 * @date 2020/4/24 2:50 下午
 */

@Service
public class SynchronizationServiceImpl implements SynchronizationService {

    @Autowired
    private UserUpdateOfVersionAndTableDao userUpdateOfVersionAndTableDao;

    @Autowired
    private UserIndexDao userIndexDao;

    @Autowired
    private IndexNoFeignService indexNoFeignService;

    @Autowired
    private JournalFeignService journalFeignService;

    @Autowired
    private AuthorIndexDao authorIndexDao;

    @Autowired
    private IJournalDao journalDao;


    @Autowired
    private JournalPaperFeignService journalPaperFeignService;

    @Override
    public List<UserSyncRecord> syncDataList(User curUser) {
        UserUpdateOfVersionAndTable userUpdateOfVersionAndTable = userUpdateOfVersionAndTableDao.queryByUserNo(curUser.getUserNo());
        List<UserIndexNoTable> userIndexNoTableList =userIndexDao.queryByBeginTime(userUpdateOfVersionAndTable.getDateTime(),curUser.getUserNo());
        List<UserSyncRecord> result = userIndexNoTableList.stream().map(UserSyncRecord::of).collect(Collectors.toList());
        return result;
    }

    /**
     * 核心方法
     *
     * @param request
     * @return
     */

    @Override
    public Result syncEntity(SyncEntityRequest request) {
        //如果是期刊的同步
        Result result = null;
        if(Constans.IndexCode.JOURNAL_CN.equals(request.getIndexCode()) ||
                Constans.IndexCode.JOURNAL_EN.equals(request.getIndexCode())){
            result = handleJournalSync(request);
        }
        if(Constans.IndexCode.JOURNAL_PAPER_CN.equals(request.getIndexCode()) ||
                Constans.IndexCode.JOURNAL_PAPER_EN.equals(request.getIndexCode())){
            result = handleJournalPaperSync(request);
        }
        //TODO  下面写其他类型同步

        if (result == null){
            result = Result.fail("暂不支持改类型的文献同步");
        }
        return result;
    }

    //期刊处理
    private Result handleJournalSync(SyncEntityRequest request){
        Result result = null;
        if (!
                (Constans.IndexCode.JOURNAL_CN.equals(request.getIndexCode()) ||
                Constans.IndexCode.JOURNAL_EN.equals(request.getIndexCode()))
        ){
            return result;
        }

        // 新增
        if (Constans.StatusValue.INSERT.equals(request.getStatus())){
            //远程调用返回的结果
            Result response =  journalFeignService.syncJournal(createJournalRequest(request));

            if (response.getCode() == SuccessEnum.JOURNAL_INDEX_SAME_AND_NATURE_DIFFERENT.getCode()){
                result = Result.successMsg(response.getMessage());
            }
            else if (response.getCode() == SuccessEnum.INDEX_REDISTRIBUTION.getCode()){
                // 本地重新分配索引号  需要刷新数据库
                redistribution(response,request);
                result = Result.fail("与服务器索引号冲突，已生成新的索引，请再同步一遍");
            }
            else if (response.getCode() == SuccessEnum.JOURNAL_INDEX_NOT_SAME_BUT_NATURE_SAME.getCode()){
                String newIndexNo = (String) response.getData();
                flushIndexNo(request.getIndexNo(),newIndexNo);
                result = Result.successMsg(response.getMessage());
            }
            else if (response.getCode() == SuccessEnum.JOURNAL_NEW.getCode()) {
                result = Result.successMsg(response.getMessage());
            }else {
                result = Result.fail("连接失败或服务端错误");
            }
        }

        //以下继续写  修改  删除的场景
        return result;
    }


    //期刊paper处理
    private Result handleJournalPaperSync(SyncEntityRequest request) {
        Result result = null;
        if (!
                (Constans.IndexCode.JOURNAL_PAPER_CN.equals(request.getIndexCode()) ||
                        Constans.IndexCode.JOURNAL_PAPER_EN.equals(request.getIndexCode()))
        ){
            return result;
        }

        if (Constans.StatusValue.INSERT.equals(request.getStatus())) {
            //远程调用返回的结果
            Result response = journalPaperFeignService.syncJournalPaper(createJournalPaperRequest(request));

            //会出现四种情况
            if (response.getCode() == SuccessEnum.JOURNAL_PAPER_SAME_AND_NATURE_DIFFERENT.getCode()){
                result = Result.successMsg(response.getMessage());
            }
            else if (response.getCode() == SuccessEnum.JOURNAL_PAPER_INDEX_REDISTRIBUTION.getCode()){
                redistribution(response,request);
                result = Result.fail("与服务器索引号冲突，已生成新的索引，请再同步一遍");
            }
            else if (response.getCode() == SuccessEnum.JOURNAL_PAPER_INDEX_NOT_SAME_BUT_NATURE_SAME.getCode()){
                String newIndexNo = (String) response.getData();
                flushIndexNo(request.getIndexNo(),newIndexNo);
                result = Result.successMsg(response.getMessage());
            }
            else if (response.getCode() == SuccessEnum.JOURNAL_PAPER_NEW.getCode()){
                result = Result.successMsg(response.getMessage());
            }
            else {
                result = Result.fail("服务端错误");
            }

        }
        return result;
    }


    private SyncJournalRequest createJournalRequest(SyncEntityRequest request){
        SyncJournalRequest syncJournalRequest = new SyncJournalRequest();

        User curUser = UserUtil.getCurUser();
        UserIndexNoTable userIndexNoTable =  userIndexDao.queryByuserAndindex(curUser.getUserNo(),request.getIndexNo());
        AuthorIndex authorIndex = authorIndexDao.queryByIndexNo(request.getIndexNo());

        syncJournalRequest.setAuthorIndex(authorIndex);
        syncJournalRequest.setUserIndexNoTable(userIndexNoTable);

        if (Constans.IndexCode.JOURNAL_EN.equals(request.getIndexCode())){
            //英文文献
            JournalEnglish journalEnglish = journalDao.queryJournalEnglishLimit1(request.getIndexNo());
            syncJournalRequest.setJournalEnglish(journalEnglish);
        }
        if (Constans.IndexCode.JOURNAL_CN.equals(request.getIndexCode())){
            //中文文献
            JournalChinese journalChinese = journalDao.queryOneJournalChineseByIndexNo(request.getIndexNo());
            syncJournalRequest.setJournalChinese(journalChinese);
        }
        return syncJournalRequest;
    }


    private SyncJournalPaperRequest createJournalPaperRequest(SyncEntityRequest request){
        SyncJournalPaperRequest syncJournalPaperRequest = new SyncJournalPaperRequest();

        User curUser = UserUtil.getCurUser();
        UserIndexNoTable userIndexNoTable =  userIndexDao.queryByuserAndindex(curUser.getUserNo(),request.getIndexNo());
        AuthorIndex authorIndex = authorIndexDao.queryByIndexNo(request.getIndexNo());

        syncJournalPaperRequest.setAuthorIndex(authorIndex);
        syncJournalPaperRequest.setUserIndexNo(userIndexNoTable);

        if (Constans.IndexCode.JOURNAL_PAPER_EN.equals(request.getIndexCode())){
            JournalPaperEnglish journalPaperEnglish = journalDao.queryJournalPaperEnglishByIndexNo(request.getIndexNo());
            syncJournalPaperRequest.setJournalPaperEnglish(journalPaperEnglish);;
        }
        if (Constans.IndexCode.JOURNAL_PAPER_CN.equals(request.getIndexCode())){
            JournalPaperChinese journalPaperChinese = journalDao.queryJournalPaperChineseByIndexNo(request.getIndexNo());
            syncJournalPaperRequest.setJournalPaperChinese(journalPaperChinese);
        }
        return syncJournalPaperRequest;
    }


    private void redistribution(Result response, SyncEntityRequest request){
        String prefix = request.getIndexCode().substring(0,request.getIndexCode().length()-1);
        List<String> indexNos = userIndexDao.queryUserIndexNoLike(prefix);
        String newIndexNo =  generateIndexNo((Character) response.getData(),indexNos);
        flushIndexNo(request.getIndexNo(),newIndexNo);
    }


    /**
     *  生成与服务器和本地都不冲突大索引
     *  入参是服务器索引号的下一个字母
     */
    private String generateIndexNo(Character serverChar,List<String> indexNos){
        char result = 'A';
        for (int i = 0; i < indexNos.size(); i++){
            String indexNo = indexNos.get(i);
            char c =  indexNo.charAt(indexNo.length()-1);
            if (result < c){
                result = c;
            }
        }

        String indexNoPrefix = indexNos.get(0).substring(0,indexNos.get(0).length()-1);
        if (serverChar > result){
            return indexNoPrefix+serverChar;
        }else {
            if (result+1 < 'Z') {
                char nextChar = (char) (result + 1);
                return indexNoPrefix + nextChar;
            }else {
                throw new BaseException(ExceptionEnum.INDEX_REDISTRIBUTION);
            }
        }
    }

    /**
     * 修改索引号
     * 先不添加事务了
     */
    private void flushIndexNo(String oldIndexNo, String newIndexNo){
        userIndexDao.updateIndexNoByIndexNo(oldIndexNo,newIndexNo);
        // 因为建立的表 是 外键形式   一个更新，其他依赖的表都变;
    }

}
